/*!
 * jQuery keyselect
 * inspired by http://www.brainfault.com/demo/selectbox/0.5/
 * initial author is brainfault@gmail.com
 * author of numerous bug fixes and type-ahead: pcherkas@gmail.com
 */
jQuery.fn.extend({
	keyselect: function(options) {
		return this.each(function() {
			new jQuery.KeySelect(this, options);
		});
	}
});

jQuery.KeySelect = function(selectobj, options) {
	
	var opt = options || {};
	opt.inputClass = opt.inputClass || "selectbox";
	opt.containerClass = opt.containerClass || "selectbox-wrapper";
	opt.overlayClass = opt.overlayClass || "selectbox-overlay";
	
	opt.hoverClass = opt.hoverClass || "selected";
	opt.debug = opt.debug || false;
	
	opt.talast = 0;
	opt.tadelay = opt.tadelay || 1000;
	opt.tastr = "";
	selectobj.opt = opt;
	
	var elm_id = selectobj.id;
	this.elm_id = elm_id;
	
	var active = 0;
	var inFocus = false;
	var hasfocus = 0;
	var $select = $(selectobj);
	var $container = setupContainer(opt);
	
	var $overlay = setupOverlay(opt);
	var $input = setupInput(opt);
	
	$select.hide().before($input).before($container).before($overlay);
	
	init();
	
	$select
	.change(function(event){
		var val1 = $select.val();
		var li = $("#"+elm_id+"_input_"+val1);
		$input.val($(li).html());
	});
	
	$input
	.click(function(){
	   if ($container.not(':visible')) {
	       inFocus = true;
	       $container.show();
	       $overlay.show();
	       moveSelect(0);
	   } else {
	       inFocus = false;
	       $container.hide();
	       $overlay.hide();
	   }
	})
	.focus(function(){
	   if ($container.not(':visible')) {
	       inFocus = true;
	       $container.show();
	       $overlay.show();	       
	   }
	})
	.keydown(function(event) {
		if (event && !event.ctrlKey){
			var now = new Date();
			if((opt.talast > 0) && (now - opt.talast) > opt.tadelay){
				opt.talast=0;
				opt.tastr="";
			}
			var keyCode = event.keyCode;

			switch(event.keyCode) {
				case 38: // up
					event.preventDefault();
					moveSelect(-1);
					opt.talast=0;
					opt.tastr="";
					if ($container.not(':visible')) {
						inFocus = true;
						$container.show();
						$overlay.show();	       
					}
					return;
				case 40: // down
					event.preventDefault();
					moveSelect(1);
					opt.talast=0;
					opt.tastr="";
					if ($container.not(':visible')) {
						inFocus = true;
						$container.show();
						$overlay.show();	       
					}
					return;
				case 13: // return
					setCurrent();
					hideMe();
					opt.talast=0;
					opt.tastr="";
					if (!$container.not(':visible')) {
						inFocus = false;
						$container.hide();
						$overlay.hide();	       
					}
					return;
			}

		   if ($container.not(':visible')) {
		       inFocus = true;
		       $container.show();
		       $overlay.show();	       
		   }

			if (keyCode >= 96 && keyCode <=105) {
				keyCode = keyCode - 48;
	 		}
			opt.tastr += String.fromCharCode(keyCode).toUpperCase();
			
			opt.talast = now;
			var txt, nearest;
			
			for (i=0; i< selectobj.options.length; i++) {
				txt = selectobj.options[i].text.toUpperCase();
				if (txt.indexOf(opt.tastr) == 0) {
					opt.last = now;
					clearTimeout(opt.tatimeout);
					var lis = $("li", $container);
					lis.removeClass(opt.hoverClass);
					var $item = $('#'+elm_id+"_input_"+selectobj.options[i].value);
					$item.addClass(opt.hoverClass);
					var targetOffset =  document.getElementById(elm_id+"_input_"+selectobj.options[i].value).offsetTop;
					$container.scrollTop(targetOffset);
					active = i;
					opt.tatimeout = setTimeout("document.getElementById(\'" + elm_id + "\').opt.tastr=\"\"; document.getElementById(\'" + elm_id + "\').opt.talast=0;", opt.tadelay);
					break;
				}
			}
		}
	});
	
   	$overlay
	.click(function(){
		hideMe();
	});


	function hideMe() { 
		hasfocus = 0;
		$container.hide();
		$overlay.hide();
	}
	
	function init() {
		$container.append(getSelectOptions($input.attr('id'))).hide();
		var width = $input.css('width');
		$input.css("width", $select.css("width"));
		$input.css("height", $select.css("height"));
		$container.css("width", $select.css("width"));
    }
	
	function setupContainer(options) {
		var container = null;
		if(document.getElementById(elm_id+'_container')){
			container = document.getElementById(elm_id+'_container')
			$container = $(container);
		} else {
			container = document.createElement("div");
			$container = $(container);
			$container.attr('id', elm_id+'_container');
			$container.addClass(options.containerClass);
		}
		return $container;
	}
	
	function setupOverlay(options) {
		var overlay = null;
		if(document.getElementById(elm_id+'_overlay')){
			overlay = document.getElementById('selectbox_overlay')
			$overlay = $(overlay);
		} else {
			overlay = document.createElement("div");
			$overlay = $(overlay);
			$overlay.attr('id', elm_id+'_overlay');
			$overlay.addClass(options.overlayClass);
		}
		return $overlay;
	}
	
	function setupInput(options) {

		if(document.getElementById(elm_id+'_input')){
			var input = document.getElementById(elm_id+'_input');
			var $input = $(input);
		} else {
			var input = document.createElement("input");
			var $input = $(input);
			$input.attr("id", elm_id+"_input");
			$input.attr("type", "text");
			$input.addClass(options.inputClass);
			$input.attr("autocomplete", "off");
			$input.attr("readonly", "readonly");
			$input.attr("tabIndex", $select.attr("tabindex"));
		}
		return $input;	
	}
	
	function moveSelect(step) {
		var lis = $("li", $container);
		if (!lis) return;

		active += step;

		if (active < 0) {
			active = 0;
		} else if (active >= lis.size()) {
			active = lis.size() - 1;
		}

		lis.removeClass(opt.hoverClass);

		var $item = $(lis[active]);
		$item.addClass(opt.hoverClass);

		var targetOffset =  document.getElementById(elm_id+"_input_"+selectobj.options[active].value).offsetTop;
		$container.scrollTop(targetOffset);
	}
	
	function setCurrent() {	
		var li = $("li."+opt.hoverClass, $container).get(0);
		var ar = (''+li.id).split('_');
		var el = ar[ar.length-1];
		//$select.val(el);
		$select.val(el).attr("selectedIndex", $container.find("li").index(li)).trigger("onchange");
		$input.val($(li).html());
		return true;
	}
	
	// select value
	function getCurrentSelected() {
		return $select.val();
	}
	
	// input value
	function getCurrentValue() {
		return $input.val();
	}
	
	function getSelectOptions(parentid) {
		var select_options = new Array();

		var ul = null;
		if(document.getElementById(parentid + "_ul")){
			ul = document.getElementById(parentid + "_ul");
		} else {
			ul = document.createElement('ul');
		}
			$select.children('option').each(function() {
				var li = null;
				if(document.getElementById(parentid + '_' + $(this).val())){
					li = document.getElementById(parentid + '_' + $(this).val());
				} else {
					li = document.createElement('li');
					li.setAttribute('id', parentid + '_' + $(this).val());
					li.innerHTML = $(this).html();
					ul.appendChild(li);
				}
				if ($(this).is(':selected')) {
					$input.val($(this).html());
					$(li).addClass(opt.hoverClass);
				}
				$(li)
				.mouseover(function(event) {
					hasfocus = 1;
					jQuery(event.target, $container).addClass(opt.hoverClass);
				})
				.mouseout(function(event) {
					hasfocus = -1;
					jQuery(event.target, $container).removeClass(opt.hoverClass);
				})
				.click(function(event) {
					$(this).addClass(opt.hoverClass);
					setCurrent();
					hideMe();
					$select.change();
				});
			});

		return ul;
	}
};
